package com.qjc.demo.thread;

import java.util.concurrent.*;

/**
 * @Description: 线程池原理
 * @Author: qjc
 * @Date: 2020/5/12
 */
public class ThreadPoolDemo {

    public static void main(String[] args) {
        /**
         * 线程池初始化方法
         *
         * corePoolSize             核心线程池大小----5
         * maximumPoolSize          最大线程池大小----10
         * keepAliveTime            线程池中超过corePoolSize数目的空闲线程最大存活时间----200+单位TimeUnit
         * TimeUnit                 keepAliveTime时间单位----TimeUnit.MILLISECONDS
         * workQueue                阻塞队列----new ArrayBlockingQueue<Runnable>(5)==== 5容量的阻塞队列
         * threadFactory            新建线程工厂----new CustomThreadFactory()====定制的线程工厂
         * rejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时, 即当提交第16个任务时(前面线程都没有执行完,此测试方法中用sleep(1000)), 任务会交给RejectedExecutionHandler来处理
         */
        ThreadPoolExecutor exec = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                //打印丢弃的任务
                long taskCount = executor.getTaskCount();
                System.out.println(r.toString() + "被拒绝 ======== 线程池中的任务数：" + taskCount);
            }
        });
        //内置四种拒绝策略
//        exec.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy ());//默默丢弃无法处理的任务，不予任何处理
//        exec.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//直接抛异常，阻止系统正常工作。
//        exec.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());//丢弃队列中最老的任务, 尝试再次提交当前任务
//        exec.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//将任务分给调用线程来执行,运行当前被丢弃的任务，这样做不会真的丢弃任务，但是提交的线程性能有可能急剧下降。
        for (int i = 1; i <= 20; i++) {//一共20个任务
            MyTask myTask = new MyTask(i);
            exec.submit(myTask);
            System.out.println("线程池中数目：" + exec.getPoolSize() + "，队列中等待执行的任务数：" + exec.getQueue().size());
        }
        exec.shutdown();
    }

}

class MyTask implements Runnable {

    private int a;

    public MyTask(int a) {
        this.a = a;
    }

    @Override
    public void run() {
        System.out.println("===============================线程ID：" + Thread.currentThread().getName() + "=====执行任务：" + a);
        try {
            // 设置线程执行时间是1000ms，这样可以保证线程池中线程被占用完，阻塞队列也被占用完，可以更好的看出线程池中的线程数以及拒绝策略执行问题
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}